//
//  YKNewSectionCollectionView.m
//  YK_SectionViewModel
//
//  Created by edward on 2021/11/26.
//  Copyright © 2021 YK_SectionViewModel. All rights reserved.
//

#import "YKCoreSectionCollectionView.h"
#import "YKCoreSectionViewModelResuseProtocol.h"
#import "YKCoreSectionNoDataView.h"

@interface YKCoreSectionCollectionView ()<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
///
@property (nonatomic, strong, readwrite) NSMutableArray<id<YKCoreSectionViewModelMainProtocol>> *datas;
///
@property (nonatomic, strong, readwrite) YKCoreSectionNoDataView *noDataView;
///
@property (nonatomic, assign, readwrite) BOOL loading;
///
@property (nonatomic, strong, readwrite) NSMutableArray *objcs;
@end

@implementation YKCoreSectionCollectionView

- (instancetype)initWithFrame:(CGRect)frame datas:(NSArray<id<YKCoreSectionViewModelMainProtocol>> *)datas
{
    if (self = [super initWithFrame:frame collectionViewLayout:[[UICollectionViewFlowLayout alloc] init]]) {
        self.datas = [datas mutableCopy];
        [self setupUI];
        [self bindData];
    }
    return self;
}

- (void)setupUI
{
    self.outTime = 15;
    self.delegate = self;
    self.dataSource = self;
    self.alwaysBounceVertical = YES;
    self.alwaysBounceHorizontal = NO;
    self.backgroundColor = UIColor.clearColor;
    [self initData];
    [self registerClass:UICollectionViewCell.class forCellWithReuseIdentifier:@"UICollectionViewCell"];
    [self registerClass:UICollectionReusableView.class forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"UICollectionReusableView"];
    [self registerClass:UICollectionReusableView.class forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"UICollectionReusableView"];
}

- (void)bindData
{
    //不在默认提供刷新
//    [self refreshDataWithMode:YKCoreSectionViewModelRefreshModeHeader];
}

- (void)initData
{
    [self.noDataView removeFromSuperview];
    [self addSubview:self.noDataView];
    for (id<YKCoreSectionViewModelMainProtocol> obj in self.datas) {
        if ([obj respondsToSelector:@selector(yksc_registItems)]) {
            NSArray<YKCoreSectionSectionResuseModel *> *models = [obj yksc_registItems];
            for (YKCoreSectionSectionResuseModel *model in models) {
                if ([model isKindOfClass:YKCoreSectionSectionResuseModel.class]) {
                    Class cellClass = NSClassFromString(model.className);
                    [self registerClass:cellClass forCellWithReuseIdentifier:model.Id];
                }
            }
        }
        
        if ([obj respondsToSelector:@selector(yksc_registHeaders)]) {
            NSArray<YKCoreSectionSectionResuseModel *> *models = [obj yksc_registHeaders];
            for (YKCoreSectionSectionResuseModel *model in models) {
                [self registerClass:NSClassFromString(model.className) forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:model.Id];
            }
        }
        
        if ([obj respondsToSelector:@selector(yksc_registFooters)]) {
            NSArray<YKCoreSectionSectionResuseModel *> *models = [obj yksc_registFooters];
            for (YKCoreSectionSectionResuseModel *model in models) {
                [self registerClass:NSClassFromString(model.className)  forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:model.Id];
            }
        }
    }
    
}


- (void)resetViewModels:(NSArray<id<YKCoreSectionViewModelMainProtocol>> *)viewModels
{
    self.datas = [viewModels mutableCopy];
    [self initData];
    [self reloadData];
}

- (void)refreshDataWithMode:(YKCoreSectionViewModelRefreshMode)mode
{
    if (self.loading) {
        //已经加载中
        return;
    }else {
        self.loading = YES;
        if (self.loadingCallBack) {
            self.loadingCallBack(YES);
        }
        [self startTimer];
    }
    
    if (self.datas.count <= 0) {
        self.loading = NO;
        if (self.loadingCallBack) {
            self.loadingCallBack(NO);
        }
        [self stopTimer];
        [self reloadData];
        return;
    }
    
    __weak typeof(self) weakself = self;
    void(^reloadBlock)(id<YKCoreSectionViewModelMainProtocol> obj) = ^(id<YKCoreSectionViewModelMainProtocol> obj){
        __strong typeof(weakself) strongself = weakself;
        NSString *objcName = [NSString stringWithFormat:@"%p",obj];
        if (strongself.objcs.count > 0) {
            [strongself.objcs removeObjectAtIndex:[strongself.objcs indexOfObject:objcName]];
        }
        if (strongself.objcs.count <= 0) {
            if (strongself.loading) {
                strongself.loading = NO;
                if (strongself.loadingCallBack) {
                    strongself.loadingCallBack(NO);
                }
                [strongself stopTimer];
                [strongself reloadData];
            }else {
                [strongself reloadData];
            }
        }
    };
    
    
    for (id<YKCoreSectionViewModelMainProtocol> obj in self.datas) {
        NSString *objcName = [NSString stringWithFormat:@"%p",obj];
        [self.objcs addObject:objcName];
    }
    
    
    for (id<YKCoreSectionViewModelMainProtocol> obj in self.datas) {
        if ([obj respondsToSelector:@selector(yksc_beignToReloadDataWithMode:reloadBlock:errorBlock:)]) {
            __weak typeof(self) weakself = self;
            [obj yksc_beignToReloadDataWithMode:mode reloadBlock:^{
                reloadBlock(obj);
            } errorBlock:^(NSError * _Nonnull error) {
                __strong typeof(weakself) strongself = weakself;
                if (strongself.errorCallBack) {
                    strongself.errorCallBack(error);
                }
            }];
        }
    }
}

- (void)setNoDataViewTip:(NSString *)tip font:(UIFont *)font
{
    self.noDataView.tipLabel.text = tip;
    self.noDataView.tipLabel.font = font;
}

- (void)setNoDataViewImage:(UIImage *)image
{
    self.noDataView.errorImageView.image = image;
}

- (void)reloadData
{
    if (self.endRefresh) {
        self.endRefresh();
    }
    [super reloadData];
    if (self.datas.count > 0) {
        NSInteger sumCount = 0;
        for (id<YKCoreSectionViewModelMainProtocol> obj in self.datas) {
            if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
                sumCount = sumCount + [obj yksc_numberOfItem];
            }
            if (sumCount <= 0) {
                self.noDataView.hidden = NO;
            }else {
                self.noDataView.hidden = YES;
            }
        }
    }else {
        self.noDataView.hidden = NO;
    }
    
}

#pragma mark - UICollectionViewDataSource

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return self.datas.count;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[section];
    NSInteger items = 0;
    if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
        items = [obj yksc_numberOfItem];
    }
    return items;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell<YKCoreSectionViewModelResuseProtocol> *cell = nil;
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[indexPath.section];
    if ([obj respondsToSelector:@selector(yksc_idForItemAtIndexPath:)]) {
        NSString *Id = [obj yksc_idForItemAtIndexPath:indexPath];
        cell = [collectionView dequeueReusableCellWithReuseIdentifier:Id forIndexPath:indexPath];
    }
    if (cell == nil) {
        if (self.errorCallBack) {
            self.errorCallBack([self createError:[NSString stringWithFormat:@"%@,cellId有误",indexPath]]);
        }
        cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"UICollectionViewCell" forIndexPath:indexPath];
    }else{
        if ([cell respondsToSelector:@selector(loadDataWithViewModel:atIndexPath:)]) {
            [cell loadDataWithViewModel:obj atIndexPath:indexPath];
        }
    }
    
    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[indexPath.section];
    
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        if ([obj respondsToSelector:@selector(yksc_idForHeader)]) {
            NSInteger items = 0;
            BOOL isShow = YES;
            if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
                items = [obj yksc_numberOfItem];
            }
            if ([obj respondsToSelector:@selector(yksc_noDataShowHeaderFooter)]) {
                isShow = [obj yksc_noDataShowHeaderFooter];
            }
            if (items > 0 || isShow) {
                NSString *HeaderId = [obj yksc_idForHeader];
                if (HeaderId && HeaderId.length > 0) {
                    UICollectionReusableView<YKCoreSectionViewModelResuseProtocol> *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:HeaderId forIndexPath:indexPath];
                    if ([headerView respondsToSelector:@selector(loadDataWithViewModel:atIndexPath:)]) {
                        [headerView loadDataWithViewModel:obj atIndexPath:indexPath];
                    }
                    return headerView;
                }
            }else {
                return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"UICollectionReusableView" forIndexPath:indexPath];
            }
        }
    }else if ([kind isEqualToString:UICollectionElementKindSectionFooter]){
        if ([obj respondsToSelector:@selector(yksc_idForFooter)]) {
            
            NSInteger items = 0;
            BOOL isShow = YES;
            if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
                items = [obj yksc_numberOfItem];
            }
            if ([obj respondsToSelector:@selector(yksc_noDataShowHeaderFooter)]) {
                isShow = [obj yksc_noDataShowHeaderFooter];
            }
            
            if (items > 0 || isShow) {
                NSString *FooterId = [obj yksc_idForFooter];
                if (FooterId && FooterId.length > 0) {
                    UICollectionReusableView<YKCoreSectionViewModelResuseProtocol> *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:FooterId forIndexPath:indexPath];
                    if ([footerView respondsToSelector:@selector(loadDataWithViewModel:atIndexPath:)]) {
                        [footerView loadDataWithViewModel:obj atIndexPath:indexPath];
                    }
                    return footerView;
                }
            }else {
                return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"UICollectionReusableView" forIndexPath:indexPath];
            }
        }
    }
    
    
    return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"UICollectionReusableView" forIndexPath:indexPath];
}


- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[indexPath.section];
    if ([obj respondsToSelector:@selector(yksc_didSelectItemAtIndexPath:collectionView:callBack:)]) {
        __weak typeof(self) weakself = self;
        [obj yksc_didSelectItemAtIndexPath:indexPath collectionView:self callBack:^(UIViewController * _Nonnull viewcontroller, YKCoreSectionViewModelPushType type, BOOL animated) {
            __strong typeof(weakself) strongself = weakself;
            if (strongself.handleViewController) {
                strongself.handleViewController(viewcontroller, type, animated);
            }
        }];
    }
}

#pragma mark - UICollectionViewDelegateFlowLayout

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[indexPath.section];
    if ([obj respondsToSelector:@selector(yksc_sizeOfItemWithWidth:AtIndexPath:)]) {
        return [obj yksc_sizeOfItemWithWidth:collectionView.bounds.size.width AtIndexPath:indexPath];
    }else{
        return CGSizeMake(collectionView.bounds.size.width, 0);
    }
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[section];
    CGSize result = CGSizeMake(collectionView.bounds.size.width, 0);
    NSInteger items = 0;
    BOOL isShow = YES;
    if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
        items = [obj yksc_numberOfItem];
    }
    if ([obj respondsToSelector:@selector(yksc_noDataShowHeaderFooter)]) {
        isShow = [obj yksc_noDataShowHeaderFooter];
    }
    
    if (items > 0 || isShow) {
        if ([obj respondsToSelector:@selector(yksc_sizeOfHeaderWithWidth:)]) {
            result = [obj yksc_sizeOfHeaderWithWidth:collectionView.bounds.size.width];
        }
    }
    return result;
    
    
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[section];
    CGSize result = CGSizeMake(collectionView.bounds.size.width, 0);
    NSInteger items = 0;
    BOOL isShow = YES;
    if ([obj respondsToSelector:@selector(yksc_numberOfItem)]) {
        items = [obj yksc_numberOfItem];
    }
    if ([obj respondsToSelector:@selector(yksc_noDataShowHeaderFooter)]) {
        isShow = [obj yksc_noDataShowHeaderFooter];
    }
    
    if (items > 0 || isShow) {
        if ([obj respondsToSelector:@selector(yksc_sizeOfFooterWithWidth:)]) {
            result = [obj yksc_sizeOfFooterWithWidth:collectionView.bounds.size.width];
        }
    }
    
    return result;
    
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[section];
    if ([obj respondsToSelector:@selector(yksc_sectionMinimumLineSpacing )]){
        return [obj yksc_sectionMinimumLineSpacing];
    }else{
        return 0;
    }
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    id<YKCoreSectionViewModelMainProtocol> obj = self.datas[section];
    if ([obj respondsToSelector:@selector(yksc_sectionMinimumInteritemSpacing)]) {
        return [obj yksc_sectionMinimumInteritemSpacing];
    }else{
        return 0;
    }
}


- (BOOL)handleRouterEvent:(NSString *)eventName userInfo:(NSDictionary *)userInfo
{
    BOOL result = NO;
    
    for (id<YKCoreSectionViewModelMainProtocol> obj in self.datas) {
        if ([obj respondsToSelector:@selector(yksc_handleRouterEvent:collectionView:userInfo:controllerEvent:)] && self.handleViewController) {
            result = ([obj yksc_handleRouterEvent:eventName collectionView:self userInfo:userInfo controllerEvent:self.handleViewController] || result);
        }
    }
    return result;
}


#pragma mark -error

- (NSError *)createError:(NSString *)message
{
    return [NSError errorWithDomain:@"YKNewSectionCollectionView" code:-1 userInfo:@{NSLocalizedDescriptionKey:message}];
}

#pragma mark -getter/setter

- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
{
    if (delegate != self) {
#ifdef DEBUG // 调试
        NSLog(@"❎YKCoreSectionCollectionView error:%@ ❎",[NSString stringWithFormat:@"无法设置delegate"]);
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"无法设置delegate" preferredStyle:UIAlertControllerStyleAlert];
        [alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [super setDelegate:self];
            [self reloadData];
        }]];
        [alertVC addAction:[UIAlertAction actionWithTitle:@"强制替换" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
            [super setDelegate:delegate];
            [self reloadData];
        }]];
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertVC animated:YES completion:nil];
#else
#endif
    }else {
        [super setDelegate:self];
    }

}

- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource
{
    if (dataSource != self) {
#ifdef DEBUG // 调试
        NSLog(@"❎YKCoreSectionCollectionView error:%@ ❎",[NSString stringWithFormat:@"无法设置dataSource"]);
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"无法设置delegate" preferredStyle:UIAlertControllerStyleAlert];
        [alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [super setDataSource:self];
            [self reloadData];
        }]];
        [alertVC addAction:[UIAlertAction actionWithTitle:@"强制替换" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
            [super setDataSource:dataSource];
            [self reloadData];
        }]];
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertVC animated:YES completion:nil];
#else
#endif
    }else {
        [super setDataSource:self];
    }
}

- (void)setAlwaysBounceHorizontal:(BOOL)alwaysBounceHorizontal
{
    [super setAlwaysBounceHorizontal:alwaysBounceHorizontal];
}

- (void)setAlwaysBounceVertical:(BOOL)alwaysBounceVertical
{
    [super setAlwaysBounceVertical:alwaysBounceVertical];
}

#pragma mark -private

- (void)startTimer
{
    [self performSelector:@selector(outTimeTodo) withObject:nil afterDelay:self.outTime];
}

- (void)stopTimer
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(outTimeTodo) object:nil];
}

- (void)outTimeTodo
{
    self.loading = NO;
    if (self.loadingCallBack) {
        self.loadingCallBack(NO);
    }
    [self.objcs removeAllObjects];
    [self reloadData];
    if (self.errorCallBack) {
        self.errorCallBack([self createError:@"加载超时"]);
    }
}

- (NSMutableArray<id<YKCoreSectionViewModelMainProtocol>> *)datas
{
    if (!_datas) {
        _datas = [NSMutableArray array];
    }
    return _datas;
}

- (YKCoreSectionNoDataView *)noDataView
{
    if (!_noDataView) {
        _noDataView = [[YKCoreSectionNoDataView alloc] initWithFrame:self.bounds];
        __weak typeof(self) weakself = self;
        _noDataView.reloadCallBack = ^{
            __strong typeof(weakself) strongself = weakself;
            [strongself refreshDataWithMode:YKCoreSectionViewModelRefreshModeHeader];
        };
    }
    return _noDataView;
}

@end
